#include <cstdio>
#include <cerrno>
#include <cstdlib>
#include <ctime>
#include <cstring>

#include <unistd.h>
#include <stdarg.h>

#include "gingko.h"
#include "gp_log.h"

extern s_gingko_global_t gko;
pthread_mutex_t g_logcut_lock = PTHREAD_MUTEX_INITIALIZER;

static pthread_key_t g_proformace_time_key;
static pthread_once_t key_once = PTHREAD_ONCE_INIT;

static const char* LOG_DIC[] = {"FATAL", "WARN", "NOTICE", "TRACE", "DEBUG"};

size_t gettimestr(char* time, const char* format, struct timeval* tv)
{
    struct tm ltime;
    time_t curtime;
    gettimeofday(tv, NULL);
    curtime = tv->tv_sec;

    return strftime(time, 25, format, localtime_r(&curtime, &ltime));
}

static void make_key()
{
    pthread_key_create(&g_proformace_time_key, NULL); // pthread key create
}

static struct timeval* get_timer(void)
{
    void* p = NULL;

    pthread_once(&key_once, make_key); // pthread once
    p = pthread_getspecific(g_proformace_time_key); // pthread get specific
    if (p == NULL)
    {
        p = calloc(1, sizeof(struct timeval));
        pthread_setspecific(g_proformace_time_key, p); // pthread set specific
    }

    return (struct timeval*) p;
}

void gko_log_flf(const uint8_t log_level, const char* file,
                 const int line, const char* func,
                 const char* fmt, ...)
{
    if (gko.opt.to_debug || log_level < DEBUG)
    {
        // TODO:
    }
}

int lock_log(void)
{
    return pthread_mutex_lock(&g_logcut_lock); // pthread mutex lock
}

int unlock_log(void)
{
    return pthread_mutex_unlock(&g_logcut_lock);
}

int reinit_log_lock(void)
{
    return pthread_mutex_init(&g_logcut_lock, NULL);
}